package cbcr;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Types;
import java.util.ArrayList;



import com.mysql.jdbc.CallableStatement;

public class CBCRCalculations {

    int totalGREScore, totalTOEFLScore;
    private Connection conn = null;

    public CBCRCalculations() {
        totalGREScore = 1600;
        totalTOEFLScore = 120;
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection("jdbc:mysql://localhost/cbcr",
                    "cbcruser", "cbcrpwd");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * Calculates the score recommender should actually give to the student
     * based on history 1. Searches for the recommender_name in the database for
     * enrolled students and gets the gpa for such students 2. Searches for the
     * recommender_name in the database for enrolled students and gets the
     * recommender_score for such students 3. Now compares the gpa and
     * recommender_score and checks for tolerance level and calculates the
     * success percentage for the recommender and accordingly returns the score
     * for new student
     *
     * This method needs to be called for every recommender for the new
     * candidate It uses the two stored procedures getRecommendedScore and
     * getRecommenderGPA
     */
    OutputCandidate getRecommenderScore(String recommender_name, double recoScore) {

        CallableStatement cStmt1 = null;
        CallableStatement cStmt2 = null;
        double gpa, recommendedScore;
        double tolerance = 1;
        double failurePoints = 0;
        double averageFailurePercent = 0;
        int i;
        int totalCases = 0;
        ArrayList<Integer> supportingCases = new ArrayList<Integer>();
        ArrayList<Double> failedCasePercentage = new ArrayList<Double>();
        OutputCandidate outCandidate = new OutputCandidate();

        System.out.println("RecoScore Cal : Reco_name : " + recommender_name + " recoScore: " + recoScore);
        try {

            //Searches for the recommender_name in the database for enrolled students and gets the gpa for such students
            cStmt1 = (CallableStatement) conn.prepareCall("{call getRecommenderGPA(?)}");
            cStmt1.setString("i_recommender_name", recommender_name);
            cStmt1.execute();
            ResultSet rs1 = cStmt1.getResultSet();
            //Searches for the recommender_name in the database for enrolled students and gets the recommender_score for such students
            cStmt2 = (CallableStatement) conn.prepareCall("{call getRecommendedScore(?)}");
            cStmt2.setString("i_recommender_name", recommender_name);
            cStmt2.execute();

            ResultSet rs2 = cStmt2.getResultSet();

            while (rs1.next()) {
                rs2.next();
                totalCases++;
                gpa = rs1.getDouble("gpa");


                recommendedScore = rs2.getDouble("recommended_score");

                if (totalCases < 4) {
                    supportingCases.add(rs1.getInt("student_id"));

                    
                }
                if (recommendedScore > gpa) {
                    failurePoints = recommendedScore - gpa;
                    if (failurePoints > tolerance) //failed .
                    {
                        /*if (totalCases < 4) { //store 3 cases fro explainations
                            supportingCases.add(rs1.getInt("student_id"));
                        }*/
                        System.out.println("RecoScore Cal : Reco_name : " + recommender_name + " recoScore: " + recoScore + "FAILED CASE ");
                        failedCasePercentage.add(failurePoints * 10);
                    }

                } else {
                    failurePoints = gpa - recommendedScore;
                    if (failurePoints > tolerance) //failed .
                    {
                        System.out.println("RecoScore Cal : Reco_name : " + recommender_name + " recoScore: " + recoScore + "FAILED CASE ");
                        failedCasePercentage.add(failurePoints * 10);
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        failurePoints = 0;

        //calculate average failure percentage
        for (i = 0; i < failedCasePercentage.size(); i++) {
            failurePoints += failedCasePercentage.get(i);
        }

        averageFailurePercent = failurePoints / i;

        //apply this failure percentage on the current recoscore and return the new score

        if (averageFailurePercent > 0) {
            recoScore -= (recoScore * averageFailurePercent) / 100;
        }

        //Store case ids for explaination

        outCandidate.setRecommendationScore(recoScore);
        outCandidate.setRecommendationExplanationCaseIds(supportingCases);

        return outCandidate;

    }

    double relaventExperienceBasedScore(int candidate_id) {
        double relexscore = 0;

        try {
            CallableStatement cStmt = (CallableStatement) conn.prepareCall("{?= call getRelexScore(?)}");
            cStmt.setInt("candidate_id", candidate_id);
            cStmt.registerOutParameter(1, Types.INTEGER);
            cStmt.execute();
            relexscore = cStmt.getInt(1);
            cStmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("for candidate " + candidate_id + " the relexscore is " + relexscore);
        return relexscore;
    }

    /*
     * Calculates publication based score for a candidate
     */
    double publicationBasedScoreCalculation(InputCandidate candidate) {
        double publicationBasedScore = 0.0;
        double scoreSum = 0.0;
        int totalPublications = 0;
        for (int i = 0; i < candidate.getPublicationConference().size(); i++) {
            double publicationRank = getRankFromDomainKnowledge(
                    "publicationConference", candidate.getPublicationConference().get(i));
            scoreSum = scoreSum + (publicationRank * candidate.getPublicationCountbyConference().get(i));
            totalPublications = totalPublications + candidate.getPublicationCountbyConference().get(i);
        }
        if (totalPublications > 0) {
            publicationBasedScore = scoreSum / totalPublications;
        }
        publicationBasedScore = roundToDecimalPlaces(publicationBasedScore, 2);
        return publicationBasedScore;
    }
    /*
     * Calculates the score for a particular educational institute. Here we
     * assume the name pf the educational institute passed is exactly same as
     * the one stored in the database (for previous cases and in domain
     * knowledge).
     */

    OutputCandidate educationaInstituteBasedScore(String educationalInstitute,
            String program) {
        double educationalInstituteRank = getRankFromDomainKnowledge(
                "educationalInstitute", educationalInstitute);
        ArrayList<InputCandidate> candidates = getCandidatesFromUniv(
                educationalInstitute, program);
        int totalCases = candidates.size();
        // if no previous cases found and educational institute is not present
        // in the domain knowledge
        if (totalCases == 0 && educationalInstituteRank < 0) {
            educationalInstituteRank = 0.0;
        } // if there are previous cases present and domian knowledge has the
        // educationa institute rank
        else if (totalCases > 0 && educationalInstituteRank > 0 && educationalInstituteRank < 10.1) {
            double rankSum = 0.0;
            for (InputCandidate candidate : candidates) {
                rankSum = rankSum + ((candidate.getGpa() + candidate.getVote() + educationalInstituteRank) * 10) / 30;
            }
            educationalInstituteRank = (rankSum + educationalInstituteRank) / (totalCases + 1);
        } // if previous cases are present but domain knowledge do not have the
        // institute rank
        else if (totalCases > 0 && educationalInstituteRank < 0) {
            double rankSum = 0.0;
            for (InputCandidate candidate : candidates) {
                rankSum = rankSum + ((candidate.getGpa() + candidate.getVote()) * 10) / 20;
            }
            educationalInstituteRank = (rankSum + educationalInstituteRank) / (totalCases + 1);
        }
        // if no previous cases are present but the domain knowledge contains
        // the institute rank, use the rank as it is.
        educationalInstituteRank = roundToDecimalPlaces(educationalInstituteRank, 2);
        //update the domain knowledge
        try {
            CallableStatement cStmt = (CallableStatement) conn.prepareCall("{call updateUniversityRank(?,?)}");
            cStmt.setString("i_school", educationalInstitute);
            cStmt.setDouble("i_newRank", educationalInstituteRank);
            cStmt.execute();
            cStmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        OutputCandidate outCandidate = new OutputCandidate();
        outCandidate.setEducationaInstituteBasedScore(educationalInstituteRank);
        ArrayList<Integer> supportingCases = new ArrayList<Integer>();
        for (int i = 0; i < min(3, totalCases); i++) {
            supportingCases.add(candidates.get(i).getID());
        }
        outCandidate.setEducationalInstituteExplanationCaseIds(supportingCases);
        //System.out.println("calculate new score for " + educationalInstitute + " is " + educationalInstituteRank);
        return outCandidate;
    }

    int min(int a, int b) {
        return a < b ? a : b;
    }

    private ArrayList<InputCandidate> getCandidatesFromUniv(
            String educationalInstitute, String program) {

        ArrayList<InputCandidate> candidates = new ArrayList<InputCandidate>();

        try {
            CallableStatement cStmt = (CallableStatement) conn.prepareCall("{call getCandidatesForUniv(?,?)}");
            cStmt.setString("i_school", educationalInstitute);
            cStmt.setString("i_program", program);
            cStmt.execute();
            ResultSet rs = cStmt.getResultSet();
            while (rs.next()) {
                InputCandidate candidate = new InputCandidate();
                candidate.setGpa(rs.getDouble("iugpa"));
                candidate.setVote(rs.getDouble("iuvote"));
                int candidate_id = rs.getInt("student_id");
                candidate.setID(candidate_id);
                CallableStatement cStmt1 = (CallableStatement) conn.prepareCall("{call updateCandidatesConsiderationStatus(?)}");
                cStmt1.setInt("candidate_id", candidate_id);
                cStmt1.execute();
                candidates.add(candidate);
                cStmt1.close();
            }
            rs.close();
            cStmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return candidates;
    }

    private double getRankFromDomainKnowledge(String str,
            String rankFor) {
        double calculatedRank = 0.0;
        if (str.equals("educationalInstitute")) {
            try {
                CallableStatement cStmt = (CallableStatement) conn.prepareCall("{call getRankForUniv(?)}");
                cStmt.setString("i_school", rankFor);
                cStmt.execute();
                ResultSet rs = cStmt.getResultSet();
                while (rs.next()) {
                    calculatedRank = rs.getDouble("univ_score");
                }

                rs.close();
                cStmt.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("Rank for " + rankFor + " is: " + calculatedRank);
        } else if (str.equals("publicationConference")) {
            try {
                CallableStatement cStmt = (CallableStatement) conn.prepareCall("{call getRankForPublicationConference(?)}");
                cStmt.setString("i_publicationName", rankFor);
                cStmt.execute();
                ResultSet rs = cStmt.getResultSet();
                while (rs.next()) {
                    calculatedRank = rs.getDouble("publication_rank");
                }

                rs.close();
                cStmt.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("Rank for " + rankFor + " is: " + calculatedRank);
        }

        return calculatedRank;
    }

    /*
     * Description - Calculates Score based on the actual score of the candidate
     * in a competitive exam. Input - CEName - name of the competitive exam
     * currentCEScore - score of the candidate in the competitive exam Return -
     * calculated score based on the given score
     */
    double CompetitiveExamBasedScore(String CEName, double currentCEScore) {
        double CEBasedScore = 0;
        double totalCEScore = 0;
        if (CEName.equals("GRE")) {
            totalCEScore = totalGREScore;
        } else if (CEName.equals("TOEFL")) {
            totalCEScore = totalTOEFLScore;
            if (currentCEScore == 0) {
                currentCEScore = totalCEScore;
            }
        }
        double avgGREScore = (double) getAverageScore(CEName);
        if (currentCEScore < avgGREScore) {
            double avgNormalized = (avgGREScore * 10) / totalCEScore;
            double differencePercentage = ((avgGREScore - currentCEScore) / totalCEScore) * 100;
            CEBasedScore = avgNormalized - (avgNormalized * (differencePercentage / 100));
        } else {
            CEBasedScore = (currentCEScore / totalCEScore) * 10;
        }

        return roundToDecimalPlaces(CEBasedScore, 2);
    }

    /*
     * Description - rounds off the double number to the specified decimal
     * places. Input - num - number to be rounded off decimalPlaces - number of
     * digits after decimal point Return - rounded off number
     */
    double roundToDecimalPlaces(double num, int decimalPlaces) {
        BigDecimal bd = new BigDecimal(num);
        // setScale is immutable
        bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP);
        return (bd.doubleValue());
    }

    /*
     * Description - retrieve the average score from the database for the
     * specified item (competitive exam) Input - tag - name of the item for
     * which average to be retrieved Return - average score for the specified
     * item
     */
    int getAverageScore(String tag) {

        int averageScore = 0;

        try {
            CallableStatement cStmt = (CallableStatement) conn.prepareCall("{?= call GetAverageFromAverages(?)}");
            cStmt.setString("i_tag", tag);
            cStmt.registerOutParameter(1, Types.INTEGER);
            cStmt.execute();
            averageScore = cStmt.getInt(1);
            cStmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return averageScore;
    }

    /*
     * Description - retrieve the average score from the database for the
     * specified item (competitive exam) Input - tag - name of the item for
     * which average to be retrieved Return - average score for the specified
     * item
     */
    public ArrayList<String> getFromUnivSpecificInfo(String col, String school,
            String program, String major) {

        ArrayList<String> list = new ArrayList<String>();

        try {
            CallableStatement cStmt = null;

            if (col.equals("School")) {
                cStmt = (CallableStatement) conn.prepareCall("{call getAllSchoolNames()}");
                cStmt.execute();
                ResultSet rs = cStmt.getResultSet();
                while (rs.next()) {
                    String schoolName = rs.getString("school");
                    System.out.println(schoolName);
                    list.add(schoolName);
                }
                rs.close();
            } else if (col.equals("Program")) {
                if (school.isEmpty()) {
                    list.add("No School");
                } else {
                    cStmt = (CallableStatement) conn.prepareCall("{call getProgramsForSchool(?)}");
                    cStmt.setString("i_school", school);
                    cStmt.execute();
                    ResultSet rs = cStmt.getResultSet();
                    while (rs.next()) {
                        String programName = rs.getString("program");
                        System.out.println(programName);
                        list.add(programName);
                    }
                    rs.close();
                }
            } else if (col.equals("Major")) {
                if (school.isEmpty() || program.isEmpty()) {
                    list.add("No School or program");
                } else {
                    cStmt = (CallableStatement) conn.prepareCall("{call getMajorForSchoolProgram(?, ?)}");
                    cStmt.setString("i_school", school);
                    cStmt.setString("i_program", program);
                    cStmt.execute();
                    ResultSet rs = cStmt.getResultSet();
                    while (rs.next()) {
                        String majorName = rs.getString("major");
                        System.out.println(majorName);
                        list.add(majorName);
                    }
                    rs.close();
                }
            } else {
                if (school.isEmpty() || program.isEmpty() || major.isEmpty()) {
                    list.add("No School or program or major specified");
                } else if (col.equals("AllParameters")) {
                    cStmt = (CallableStatement) conn.prepareCall("{call getParasForSchoolProgramMajor(?, ?, ?)}");
                    cStmt.setString("i_school", school);
                    cStmt.setString("i_program", program);
                    cStmt.setString("i_major", major);
                    cStmt.execute();
                    ResultSet rs = cStmt.getResultSet();
                    while (rs.next()) {
                        list.add(rs.getString("GREContriPercent"));
                        list.add(rs.getString("TOEFLContriPercent"));
                        list.add(rs.getString("EduInstiContriPercent"));
                        list.add(rs.getString("GPAContriPercent"));
                        list.add(rs.getString("PublicationContriPercent"));
                        list.add(rs.getString("RecoContriPercent"));
                        list.add(rs.getString("RelExpContriPercent"));
                    }
                    rs.close();
                }
            }

            cStmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }

    public boolean saveParameterpercents(ArrayList<Integer> percents,
            String school, String program, String major) {
        boolean success = true;
        try {
            CallableStatement cStmt = null;
            cStmt = (CallableStatement) conn.prepareCall("{call setParasForSchoolProgramMajor(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
            cStmt.setInt(1, percents.get(0));
            cStmt.setInt(2, percents.get(1));
            cStmt.setInt(3, percents.get(2));
            cStmt.setInt(4, percents.get(3));
            cStmt.setInt(5, percents.get(4));
            cStmt.setInt(6, percents.get(5));
            cStmt.setInt(7, percents.get(6));
            cStmt.setString(8, school);
            cStmt.setString(9, program);
            cStmt.setString(10, major);

            cStmt.execute();
            cStmt.close();
        } catch (Exception e) {
            e.printStackTrace();
            success = false;
        }
        return success;
    }

    /*
     * This is main function called from GUI to calculate ratings for all new
     * candidates. The ratings are based on 7 parameters GRE,TOEFL, educational
     * institute, publications, recommendations, relevant experience.
     */
    public ArrayList<OutputCandidate> calculateRatings(
            ArrayList<Integer> percents, String admissionToProgram) {
        ArrayList<InputCandidate> newCandidates = getAllNewCandidates(admissionToProgram);
        ArrayList<OutputCandidate> processedCandidates = new ArrayList<OutputCandidate>();

        for (InputCandidate newCandidate : newCandidates) {
            OutputCandidate processedCandidate = new OutputCandidate();
            double greBasedScore = 0, toeflBasedScore = 0, educationalInstituteRanking = 0;
            double publicationBasedScore = 0, relevatExperienceBasedScore = 0, recoBasedScore = 0;
            double ranking = 0;
            greBasedScore = CompetitiveExamBasedScore("GRE", newCandidate.getGREScore());
            toeflBasedScore = CompetitiveExamBasedScore("TOEFL", newCandidate.getTOEFLScore());
            OutputCandidate tempout = educationaInstituteBasedScore(newCandidate.getInstituteName(), newCandidate.getLastProgram());
            educationalInstituteRanking = tempout.getEducationaInstituteBasedScore();
            processedCandidate.setEducationalInstituteExplanationCaseIds(tempout.getEducationalInstituteExplanationCaseIds());

            publicationBasedScore = publicationBasedScoreCalculation(newCandidate);
            OutputCandidate tempout1  = getRecommenderScore(newCandidate.getRecommenderNames().get(0), newCandidate.getRecommenderScores().get(0));
            recoBasedScore = tempout1.getRecommendationScore();
            processedCandidate.setRecommendationExplanationCaseIds(tempout1.getRecommendationExplanationCaseIds());
            
            System.out.println("Reco Based Score : " + recoBasedScore + " For candidate : " + newCandidate.getID());
            relevatExperienceBasedScore = relaventExperienceBasedScore(newCandidate.getID());

            ranking = ranking + ((((double) percents.get(0)) * greBasedScore) / 100);
            ranking = ranking + ((((double) percents.get(1)) * toeflBasedScore) / 100);
            ranking = ranking + ((((double) percents.get(2)) * educationalInstituteRanking) / 100);

            ranking = ranking + ((((double) percents.get(3)) * newCandidate.getGpa()) / 100);

            ranking = ranking + ((((double) percents.get(4)) * publicationBasedScore) / 100);

            ranking = ranking + ((((double) percents.get(5)) * recoBasedScore) / 100);


            ranking = roundToDecimalPlaces(ranking, 2);

            //for relevant experience
			/*if(relevatExperienceBasedScore == 10){
            ranking = ranking + (ranking * (double)percents.get(6))/(double)100 ;
            }*/

            processedCandidate.setID(newCandidate.getID());
            processedCandidate.setName(newCandidate.getName());
            processedCandidate.setGREScore(greBasedScore);
            processedCandidate.setTOEFLScore(toeflBasedScore);
            processedCandidate.setEducationaInstituteBasedScore(educationalInstituteRanking);
            processedCandidate.setGpa(roundToDecimalPlaces(newCandidate.getGpa(), 2));
            processedCandidate.setPublicationScore(publicationBasedScore);
            processedCandidate.setRecommendationScore(recoBasedScore);
            processedCandidate.setRelevantExperienceScore(relevatExperienceBasedScore);
            processedCandidate.setTotalScore(ranking);
            processedCandidates.add(processedCandidate);
        }

          processedCandidates = sort(processedCandidates);

        return processedCandidates;
    }

    /*
     * Sorts list of output candidates order of their ratings in descending
     * manner. This is used by GUI class.
     */
    private ArrayList<OutputCandidate> sort(
            ArrayList<OutputCandidate> newCandidates) {

        ArrayList<OutputCandidate> sortedCandidates = new ArrayList<OutputCandidate>();
        int indexForMax;
        do {
            indexForMax = getCandidateWithMaxScore(newCandidates);
            if (indexForMax > -1 && indexForMax < newCandidates.size()) {
                OutputCandidate oc = new OutputCandidate();
                oc = newCandidates.get(indexForMax);
                sortedCandidates.add(oc);
                newCandidates.remove(indexForMax);
            }
            System.out.println("indexForMax: " + indexForMax + " size:" + newCandidates.size());
        } while (indexForMax > -1);
        return sortedCandidates;
    }

    private int getCandidateWithMaxScore(
            ArrayList<OutputCandidate> newCandidates) {
        double maxScore = 0;
        int index = -1, itrs = newCandidates.size();
        for (int i = 0; i < itrs; i++) {
            double candidate_tscore = newCandidates.get(i).getTotalScore();
            if (maxScore < candidate_tscore) {
                maxScore = candidate_tscore;
                index = i;
            }
        }

        return index;
    }

    /*
     * Retrieves all new candidates from database.
     */
    private ArrayList<InputCandidate> getAllNewCandidates(String program) {
        // TODO Auto-generated method stub
        ArrayList<InputCandidate> newCandidates = new ArrayList<InputCandidate>();
        CallableStatement cStmt = null;

        try {

            cStmt = (CallableStatement) conn.prepareCall("{call getAllNewCandidates(?)}");
            cStmt.setString("i_program",  program);
            cStmt.execute();
            ResultSet rs = cStmt.getResultSet();
            while (rs.next()) {
                InputCandidate newCandidate = new InputCandidate();
                newCandidate.setID(rs.getInt("student_id"));
                String name = rs.getString("first_name") + " " + rs.getString("last_name");
                newCandidate.setName(name);
                newCandidate.setGREScore(rs.getDouble("GRE_score"));
                newCandidate.setTOEFLScore(rs.getDouble("TOEFL_score"));
                newCandidate.setGpa(rs.getDouble("GPA"));
                newCandidate.setInstituteName(rs.getString("institute_name"));
                newCandidate.setLastProgram(rs.getString("program"));
                newCandidate = getRecommendationInfoForCandidate(newCandidate);
                newCandidate = getPublicationInfoForCandidate(newCandidate);
                newCandidates.add(newCandidate);
            }
            rs.close();
            cStmt.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return newCandidates;
    }

    private InputCandidate getPublicationInfoForCandidate(
            InputCandidate newCandidate) {
        InputCandidate candidate = new InputCandidate();
        int candidate_id = newCandidate.getID();
        ArrayList<String> publicationConfNames = new ArrayList<String>();
        ArrayList<Integer> publicationCountbyConf = new ArrayList<Integer>();

        candidate.setID(candidate_id);
        candidate.setName(newCandidate.getName());
        candidate.setGREScore(newCandidate.getGREScore());
        candidate.setTOEFLScore(newCandidate.getTOEFLScore());
        candidate.setGpa(newCandidate.getGpa());
        candidate.setInstituteName(newCandidate.getInstituteName());
        candidate.setLastProgram(newCandidate.getLastProgram());
        candidate.setRecommenderNames(newCandidate.getRecommenderNames());
        candidate.setRecommenderScores(newCandidate.getRecommenderScores());

        CallableStatement cStmt = null;

        try {

            cStmt = (CallableStatement) conn.prepareCall("{call getAllPublicationVenuesForCandidate(?)}");
            cStmt.setInt("candidate_id", candidate_id);
            cStmt.execute();
            ResultSet rs = cStmt.getResultSet();
            while (rs.next()) {
                publicationConfNames.add(rs.getString("conference_name"));
                publicationCountbyConf.add(rs.getInt("countofpublications"));
            }
            candidate.setPublicationConference(publicationConfNames);
            candidate.setPublicationCountbyConference(publicationCountbyConf);
            rs.close();
            cStmt.close();


        } catch (Exception e) {
            e.printStackTrace();
        }

        return candidate;
    }

    private InputCandidate getRecommendationInfoForCandidate(
            InputCandidate newCandidate) {
        InputCandidate candidate = new InputCandidate();
        int candidate_id = newCandidate.getID();
        ArrayList<String> recommenderNames = new ArrayList<String>();
        ArrayList<Double> recommenderScores = new ArrayList<Double>();

        candidate.setID(candidate_id);
        candidate.setName(newCandidate.getName());
        candidate.setGREScore(newCandidate.getGREScore());
        candidate.setTOEFLScore(newCandidate.getTOEFLScore());
        candidate.setGpa(newCandidate.getGpa());
        candidate.setInstituteName(newCandidate.getInstituteName());
        candidate.setLastProgram(newCandidate.getLastProgram());

        CallableStatement cStmt = null;

        try {

            cStmt = (CallableStatement) conn.prepareCall("{call getAllRecommendationInfoForCandidate(?)}");
            cStmt.setInt("candidate_id", candidate_id);
            cStmt.execute();
            ResultSet rs = cStmt.getResultSet();
            while (rs.next()) {
                recommenderNames.add(rs.getString("recommender_name"));
                recommenderScores.add(rs.getDouble("recommended_score"));
            }
            rs.close();
            cStmt.close();

            candidate.setRecommenderNames(recommenderNames);
            candidate.setRecommenderScores(recommenderScores);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return candidate;
    }

    public static void main(String args[]) {
        CBCRCalculations c = new CBCRCalculations();
        // System.out.println("for GRE score 1250 GREbasedScore is "
        // + c.CompetitiveExamBasedScore("GRE", 1250));
        // System.out.println("for TOEFL score 110 GREbasedScore is "
        // + c.CompetitiveExamBasedScore("TOEFL", 110));

        ArrayList<String> a = c.getFromUnivSpecificInfo("School",
                "School of Informatics and Computing", "Masters", "");
        c.getCandidatesFromUniv("National University of Singapore", "Bachlors");
        c.getRankFromDomainKnowledge("educationalInstitute",
                "National University of Singapore");
    }
}
